home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / PKTDRVR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-27  |  9.0 KB  |  389 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include <dos.h>
  4. #include "global.h"
  5. #include "proc.h"
  6. #include "mbuf.h"
  7. #include "enet.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "kiss.h"
  11. #include "iface.h"
  12. #include "ec.h"
  13. #include "timer.h"
  14. #include "arp.h"
  15. #include "trace.h"
  16. #include "pktdrvr.h"
  17. #include "config.h"
  18.  
  19. extern struct mbuf *Hopper;
  20. void pkvec0(),pkvec1(),pkvec2();
  21. void (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  22. void pkint();
  23. static int access_type(),release_type(),send_pkt(),get_address();
  24. #ifdef    notdef
  25. static int driver_info();
  26. #endif
  27.  
  28. struct pktdrvr Pktdrvr[PK_MAX];
  29. unsigned int Npk;
  30. int Derr;
  31.  
  32. /* Send raw packet (caller provides header) */
  33. int
  34. pk_raw(iface,bp)
  35. struct iface *iface;    /* Pointer to interface control block */
  36. struct mbuf *bp;    /* Data field */
  37. {
  38.     register struct pktdrvr *pp;
  39.     int16 size;
  40.     struct mbuf *bp1;
  41.  
  42.     pp = &Pktdrvr[iface->dev];
  43.     size = len_mbuf(bp);
  44.  
  45.     switch(pp->class){
  46.     case CL_ETHERNET:
  47.         dump(iface,IF_TRACE_OUT,TYPE_ETHER,bp);
  48.         if(size < 60)
  49.             size = 60;
  50.         break;
  51.     case CL_SERIAL_LINE:
  52.         dump(iface,IF_TRACE_OUT,TYPE_IP,bp);
  53.         break;
  54.     case CL_AX25:
  55.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  56.         break;
  57.     case CL_KISS:
  58.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  59.         /* This *really* shouldn't be done here, but it was the
  60.          * easiest way. Put the type field for KISS TNC on front.
  61.          */
  62.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  63.             free_p(bp);
  64.             return -1;
  65.         }
  66.         bp = bp1;
  67.         bp->data[0] = KISS_DATA;
  68.         break;
  69.     }
  70.     if(bp->next != NULLBUF){
  71.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  72.         bp1 = copy_p(bp,size);
  73.         free_p(bp);
  74.         bp = bp1;
  75.         if(bp == NULLBUF)
  76.             return -1;
  77.     } else
  78.         bp->cnt = size;    /* Make sure packet size is big enough */
  79.  
  80.     send_pkt(pp->intno,bp->data,bp->cnt);
  81.     free_p(bp);
  82.     return 0;
  83. }
  84.  
  85. /* Packet driver receive routine. Called from an assembler hook that pushes
  86.  * the caller's registers on the stack so we can access and modify them.
  87.  * This is a rare example of call-by-location in C.
  88.  */
  89. void
  90. pkint(dev,di,si,bp,dx,cx,bx,ax,ds,es)
  91. unsigned short dev,di,si,bp,dx,cx,bx,ax,ds,es;
  92. {
  93.     register struct pktdrvr *pp;
  94.     struct phdr *phdr;
  95.  
  96.     if(dev >= Npk)
  97.         return;    /* Unknown packet */
  98.     pp = &Pktdrvr[dev];
  99.  
  100.     switch(ax){
  101.     case 0:    /* Space allocate call */
  102.         if((pp->buffer = alloc_mbuf(cx+sizeof(struct phdr))) != NULLBUF){
  103.             es = FP_SEG(pp->buffer->data);
  104.             di = FP_OFF(pp->buffer->data+sizeof(struct phdr));
  105.             pp->buffer->cnt = cx + sizeof(struct phdr);
  106.             phdr = (struct phdr *)pp->buffer->data;
  107.             phdr->iface = pp->iface;
  108.             switch(pp->class){
  109.             case CL_ETHERNET:
  110.                 phdr->type = TYPE_ETHER;
  111.                 break;
  112.             case CL_SERIAL_LINE:
  113.                 phdr->type = TYPE_IP;
  114.                 break;
  115.             case CL_AX25:
  116.                 phdr->type = TYPE_AX25;
  117.                 break;
  118.             case CL_KISS:
  119.                 phdr->type = TYPE_KISS;
  120.                 break;
  121.             }
  122.         } else {
  123.             es = di = 0;
  124.         }
  125.         break;
  126.     case 1:    /* Packet complete call */
  127.         enqueue(&Hopper,pp->buffer);
  128.         pp->buffer = NULLBUF;
  129.         break;
  130.     default:
  131.         break;
  132.     }
  133. }
  134.  
  135. /* Shut down the packet interface */
  136. pk_stop(iface)
  137. struct iface *iface;
  138. {
  139.     struct pktdrvr *pp;
  140.  
  141.     pp = &Pktdrvr[iface->dev];
  142.     /* Call driver's release_type() entry */
  143.     if(release_type(pp->intno,pp->handle1) == -1)
  144.         printf("%s: release_type error code %u\n",iface->name,Derr);
  145.  
  146.     if(pp->class == CL_ETHERNET)
  147.         release_type(pp->intno,pp->handle2);
  148. }
  149. /* Attach a packet driver to the system
  150.  * argv[0]: hardware type, must be "packet"
  151.  * argv[1]: software interrupt vector, e.g., x7e
  152.  * argv[2]: interface label, e.g., "trw0"
  153.  * argv[3]: maximum number of packets allowed on receive queue, e.g., "5"
  154.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  155.  */
  156. int
  157. pk_attach(argc,argv)
  158. int argc;
  159. char *argv[];
  160. {
  161.     register struct iface *if_pk;
  162.     int class;
  163.     unsigned int intno;
  164.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  165.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  166.     long drvvec;
  167.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  168.     register struct pktdrvr *pp;
  169.  
  170.     if(Npk >= PK_MAX){
  171.         printf("Too many packet drivers\n");
  172.         return -1;
  173.     }
  174.     if(if_lookup(argv[2]) != NULLIF){
  175.         printf("Interface %s already exists\n",argv[2]);
  176.         return -1;
  177.     }
  178.  
  179.     intno = htoi(argv[1]);
  180.     /* Verify that there's really a packet driver there, so we don't
  181.      * go off into the ozone (if there's any left)
  182.      */
  183.     drvvec = (long)getvect(intno);
  184.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  185.         FP_OFF(sig),FP_SEG(sig),strlen(PKT_SIG));
  186.     if(strncmp(sig,PKT_SIG,strlen(PKT_SIG)) != 0){
  187.         printf("No packet driver loaded at int 0x%x\n",intno);
  188.         return -1;
  189.     }
  190.     if((if_pk = (struct iface *)calloc(1,sizeof(struct iface))) == NULLIF
  191.      ||(if_pk->name = strdup(argv[2])) == NULLCHAR){
  192.         free((char *)if_pk);
  193.         printf("pk_attach: no memory!\n");
  194.         return -1;
  195.     }
  196.     pp = &Pktdrvr[Npk];
  197.     if_pk->mtu = atoi(argv[4]);
  198.     if_pk->dev = Npk++;
  199.     if_pk->raw = pk_raw;
  200.     if_pk->stop = pk_stop;
  201.     pp->intno = intno;
  202.     pp->iface = if_pk;
  203.  
  204.     /* Find out by exhaustive search what class this driver is (ugh) */
  205.     for(class=0;class<9;class++){
  206.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  207.             Pkvec[if_pk->dev]);
  208.         if(pp->handle1 != -1)
  209.             break;
  210.     }
  211.     /* Now that we know, release it and do it all over again with the
  212.      * right type fields
  213.      */
  214.     release_type(intno,pp->handle1);
  215.     switch(class){
  216.     case CL_ETHERNET:
  217.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  218.             Pkvec[if_pk->dev]);
  219.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  220.             Pkvec[if_pk->dev]);            
  221.         if_pk->send = enet_send;
  222.         if_pk->output = enet_output;
  223.         /* Get hardware Ethernet address from driver */
  224.         if((if_pk->hwaddr = malloc(EADDR_LEN)) == NULLCHAR){
  225.             free(if_pk->name);
  226.             free((char *)if_pk);
  227.             printf("pk_attach: no memory!\n");
  228.             return -1;
  229.         }
  230.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  231.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,1,Ether_bdcst,pether,gaether);
  232.         break;
  233. #ifdef    SLIP
  234.     case CL_SERIAL_LINE:
  235.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  236.          Pkvec[if_pk->dev]);
  237.         if_pk->send = slip_send;
  238.         break;
  239. #endif
  240. #ifdef    KISS
  241.     case CL_KISS:    /* Note that the raw routine puts on the command */
  242.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  243.          Pkvec[if_pk->dev]);
  244.         if_pk->send = ax_send;
  245.         if_pk->output = ax_output;
  246.         break;
  247. #endif
  248. #ifdef    AX25
  249.     case CL_AX25:
  250.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  251.          Pkvec[if_pk->dev]);
  252.         if_pk->send = ax_send;
  253.         if_pk->output = ax_output;
  254.         break;
  255. #endif
  256.     default:
  257.         printf("Packet driver has unsupported class %u\n",class);
  258.         free(if_pk->name);
  259.         free((char *)if_pk);
  260.         Npk--;
  261.         return -1;
  262.     }
  263.     pp->class = class;
  264.     if_pk->next = Ifaces;
  265.     Ifaces = if_pk;
  266.  
  267.     return 0;
  268. }
  269. static int
  270. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  271. int intno;
  272. int if_class;
  273. int if_type;
  274. int if_number;
  275. char *type;
  276. unsigned typelen;
  277. void (*receiver)();
  278. {
  279.     union REGS regs;
  280.     struct SREGS sregs;
  281.  
  282.     segread(&sregs);
  283.     regs.h.dl = if_number;        /* Number */
  284.     sregs.ds = FP_SEG(type);    /* Packet type template */
  285.     regs.x.si = FP_OFF(type);
  286.     regs.x.cx = typelen;        /* Length of type */
  287.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  288.     regs.x.di = FP_OFF(receiver);
  289.     regs.x.bx = if_type;        /* Type */
  290.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  291.     regs.h.al = if_class;        /* Class */
  292.     int86x(intno,®s,®s,&sregs);
  293.     if(regs.x.cflag){
  294.         Derr = regs.h.dh;
  295.         return -1;
  296.     } else
  297.         return regs.x.ax;
  298. }
  299. static int
  300. release_type(intno,handle)
  301. int intno;
  302. int handle;
  303. {
  304.     union REGS regs;
  305.  
  306.     regs.x.bx = handle;
  307.     regs.h.ah = RELEASE_TYPE;
  308.     int86(intno,®s,®s);
  309.     if(regs.x.cflag){
  310.         Derr = regs.h.dh;
  311.         return -1;
  312.     } else
  313.         return 0;
  314. }
  315. static int
  316. send_pkt(intno,buffer,length)
  317. int intno;
  318. char *buffer;
  319. unsigned length;
  320. {
  321.     union REGS regs;
  322.     struct SREGS sregs;
  323.  
  324.     segread(&sregs);
  325.     sregs.ds = FP_SEG(buffer);
  326.     regs.x.si = FP_OFF(buffer);
  327.     regs.x.cx = length;
  328.     regs.h.ah = SEND_PKT;
  329.     int86x(intno,®s,®s,&sregs);
  330.     if(regs.x.cflag){
  331.         Derr = regs.h.dh;
  332.         return -1;
  333.     } else
  334.         return 0;
  335. }
  336. #ifdef    notdef
  337. static int
  338. driver_info(intno,handle,version,class,type,number,basic)
  339. int intno;
  340. int handle;
  341. int *version,*class,*type,*number,*basic;
  342. {
  343.     union REGS regs;
  344.  
  345.     regs.x.bx = handle;
  346.     regs.h.ah = DRIVER_INFO;
  347.     regs.h.al = 0xff;
  348.     int86(intno,®s,®s);
  349.     if(regs.x.cflag){
  350.         Derr = regs.h.dh;
  351.         return -1;
  352.     }
  353.     if(version != NULL)
  354.         *version = regs.x.bx;
  355.     if(class != NULL)
  356.         *class = regs.h.ch;
  357.     if(type != NULL)
  358.         *type = regs.x.dx;
  359.     if(number != NULL)
  360.         *number = regs.h.cl;
  361.     if(basic != NULL)
  362.         *basic = regs.h.al;
  363.     return 0;
  364. }
  365. #endif
  366. static int
  367. get_address(intno,handle,buf,len)
  368. int intno;
  369. int handle;
  370. char *buf;
  371. int len;
  372. {
  373.     union REGS regs;
  374.     struct SREGS sregs;
  375.  
  376.     segread(&sregs);
  377.     sregs.es = FP_SEG(buf);
  378.     regs.x.di = FP_OFF(buf);
  379.     regs.x.cx = len;
  380.     regs.x.bx = handle;
  381.     regs.h.ah = GET_ADDRESS;
  382.     int86x(intno,®s,®s,&sregs);
  383.     if(regs.x.cflag){
  384.         Derr = regs.h.dh;
  385.         return -1;
  386.     }
  387.     return 0;
  388. }
  389.